package tools

/*
 +----------------------------------------------------------------------
 + Title        : ConsulRegisterServer、ConsulServiceDiscovery
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2022-01-06
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : consul 服务注册与发现
 +				: 文档地址:
 +				: 插件: github.com/hashicorp/consul/api
 +----------------------------------------------------------------------
*/
import (
	"strconv"

	"github.com/hashicorp/consul/api"
)

// 定义CONSUL服务注册结构体
type ConsulServiceRegister struct {
	client *api.Client
}

// 定义CONSUL服务发现结构体
type ConsulServiceDiscovery struct {
	client *api.Client
}

/**
 * 创建CONSUL服务注册
 *
 * @param string addrs ------------------------------------------------必传
 * @param string token ------------------------------------------------必传
 * @return *ConsulServiceRegister, error
 * @author huwl
 */
func NewConsulServiceRegister(addrs, token string) (*ConsulServiceRegister, error) {
	// 初始化consul配置
	consulConfig := api.DefaultConfig()
	consulConfig.Address = addrs
	consulConfig.Token = token
	client, err := api.NewClient(consulConfig)
	if err != nil {
		return nil, err
	}

	return &ConsulServiceRegister{
		client: client,
	}, nil
}

/**
 * 创建CONSUL服务发现
 *
 * @param string addrs ------------------------------------------------必传
 * @param string token ------------------------------------------------必传
 * @return *ConsulServiceRegisterAndDiscovery, error
 * @author huwl
 */
func NewConsulServiceDiscovery(addrs, token string) (*ConsulServiceDiscovery, error) {
	// 初始化consul配置
	consulConfig := api.DefaultConfig()
	consulConfig.Address = addrs
	consulConfig.Token = token
	client, err := api.NewClient(consulConfig)
	if err != nil {
		return nil, err
	}

	return &ConsulServiceDiscovery{
		client: client,
	}, nil
}

/**
 * 注册服务
 *
 * @param []string tags -----------------------------------------------必传,[]string{"card"}
 * @param string serviceName ------------------------------------------必传
 * @param string serviceAddress ---------------------------------------必传
 * @param int servicePort ---------------------------------------------必传
 * @author huwl
 */
func (sr *ConsulServiceRegister) RegisterService(tags []string, serviceName, serviceAddress string, servicePort int) error {
	// 注册服务，服务常规配置
	registerService := api.AgentServiceRegistration{
		// ID:      "1",
		// Tags:    []string{"card"},
		// Name:    "CardService",
		// Address: "127.0.0.1",
		// Port: 8080,
		// Check: &api.AgentServiceCheck{
		// 	TCP:      "127.0.0.1:8080",
		// 	Timeout:  "5s",
		// 	Interval: "5s",
		// },
		ID:      serviceName,
		Tags:    tags,
		Name:    serviceName,
		Address: serviceAddress,
		Port:    servicePort,
		Check: &api.AgentServiceCheck{
			TCP:      serviceAddress + ":" + strconv.Itoa(servicePort),
			Timeout:  "5s",
			Interval: "5s",
		},
	}

	// 注册服务到consul
	return sr.client.Agent().ServiceRegister(&registerService)
}

/**
 * 注销服务
 *
 * @param string serviceName ------------------------------------------必传
 * @author huwl
 */
func (sr *ConsulServiceRegister) DeregisterService(serviceName string) error {
	return sr.client.Agent().ServiceDeregister(serviceName)
}

/**
 * 选择一个健康的服务
 *
 * @param string serviceName ------------------------------------------必传
 * @param string tag --------------------------------------------------必传
 * @return *api.AgentService, error
 * @author huwl
 */
func (sd *ConsulServiceDiscovery) SelectOneHealthyService(serviceName, tag string) (*api.AgentService, error) {
	//获取服务地址
	serviceEntry, _, err := sd.client.Health().Service(serviceName, tag, false, &api.QueryOptions{})
	if err != nil {
		return nil, err
	}

	return serviceEntry[0].Service, nil
}

/**
 * 选择多个健康的服务
 *
 * @param string serviceName ------------------------------------------必传
 * @param string tag --------------------------------------------------必传
 * @return []*api.ServiceEntry, error
 * @author huwl
 */
func (sd *ConsulServiceDiscovery) SelectHealthyService(serviceName, tag string) ([]*api.ServiceEntry, error) {
	//获取服务地址
	serviceEntry, _, err := sd.client.Health().Service(serviceName, tag, false, &api.QueryOptions{})
	if err != nil {
		return nil, err
	}

	return serviceEntry, nil
}

/**
 * 选择多个服务标签
 *
 * @param string serviceName ------------------------------------------必传
 * @param string tag --------------------------------------------------必传
 * @return []*api.ServiceEntry, error
 * @author huwl
 */
func (sd *ConsulServiceDiscovery) SelectServiceMultipleTags(serviceName string, tags []string) ([]*api.ServiceEntry, error) {
	//获取服务地址
	serviceEntry, _, err := sd.client.Health().ServiceMultipleTags(serviceName, tags, false, &api.QueryOptions{})
	if err != nil {
		return nil, err
	}

	return serviceEntry, nil
}
